package com.kehutong.crm.message.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.http.result.Result;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.util.Objects;
import com.kehutong.common.enums.MessageBusinessEnum;
import com.kehutong.common.enums.TemplateType;
import com.kehutong.common.util.TemplateReplaceUtil;
import com.kehutong.crm.message.entity.MessageGlobalConfig;
import com.kehutong.crm.message.entity.MessageTemplateSms;

@WebService("/crm/message/sms/service")
public class MessageSmsService {

    private static final Logger logger = LoggerFactory.getLogger(MessageSmsService.class);

    @Inject
    private JdbcSession jdbcSession;
    @Inject
    private TencentSmsService tencentSmsService;
    @Inject
    private MessageGlobalConfigService globalConfigService;

    public Object listPage(JSONObject jsonObject) {
        return Result.success(jdbcSession.findPage(MessageTemplateSms.class)
                                         .like(jsonObject, "name")
                                         .eq("deleted", false)
                                         .order("createTIme", "desc")
                                         .page(jsonObject)
                                         .exe());
    }

    public Object save(MessageTemplateSms sms) {
        if (TemplateReplaceUtil.checkTrim(sms.getContent()))
            return Result.error(0, "模板内容里边${}中必须要有值");

        try {
            return refreshNewSmsTemplate(sms);
        } catch (Exception e){
            logger.error(e.getMessage(), e);
            return Result.error(0, e.getMessage());
        }
    }

    public Object update(MessageTemplateSms sms) {
        if (TemplateReplaceUtil.checkTrim(sms.getContent()))
            return Result.error(0, "参数${}中必须要有值");

        try {

            return refreshNewSmsTemplate(sms);
        }catch (Exception e) {
            logger.error(e.getMessage(), e);
            return Result.error(0, e.getMessage());
        }
    }

    public Object delete(MessageTemplateSms sms) {
        sms.setDeleted(true);
        jdbcSession.updateById(sms);

        return Result.success();
    }

    public Object refreshStatus(){
        List<MessageTemplateSms> list = jdbcSession.findArray(MessageTemplateSms.class)
                                                   .eq("status", 0)
                                                   .eq("deleted", false)
                                                   .noEq("statusCode", 0)
                                                   .exe();

        if (Objects.isEmpty(list))
            return Result.success();

        Set<Integer> templateIdList = list.stream()
                                          .filter(e -> e.getTencentTemplateId() > 0)
                                          .map(MessageTemplateSms::getTencentTemplateId)
                                          .collect(Collectors.toSet());

        if (Objects.isEmpty(templateIdList))
            return Result.success();

        try {
            JSONObject resultJson = tencentSmsService.queryTemplate(new ArrayList<>(templateIdList));
            logger.info("查询模板返回：{}", resultJson.toJSONString());
            JSONObject resJson = resultJson.getJSONObject("Response");
            JSONArray jsonArray = resJson.getJSONArray("DescribeTemplateStatusSet");
            if (Objects.isEmpty(jsonArray)){
                return Result.error(0, "刷新状态的数据为空");
            }

            Map<Integer, JSONObject> map = new HashMap<>();
            jsonArray.forEach(e -> {
                JSONObject tempJson = (JSONObject) e;
                map.put(tempJson.getInteger("TemplateId"), tempJson);
            });

            for(MessageTemplateSms sms: list){
                if (map.containsKey(sms.getTencentTemplateId())){
                    JSONObject tempJson = map.get(sms.getTencentTemplateId());
                    Integer statusCode = tempJson.getInteger("StatusCode");
                    if (Objects.isNull(statusCode)) {
                        continue;
                    }

                    if (statusCode == 0){// 0：表示审核通过。1：表示审核中。-1：表示审核未通过或审核失败
                        MessageTemplateSms templateSms = getSmsByEnable(sms.getTemplateType().getId());
                        if (Objects.nonNull(templateSms) && !templateSms.getId().equals(sms.getId())){
                            // set disabled
                            templateSms.setStatus(2);
                            jdbcSession.updateById(templateSms);
                        }

                        // sync global config
                        resetGlobalConfig(sms.getId());
                        syncGlobalConfig(sms.getBusinessType(), sms.getTemplateType(), sms.getId());

                        // reset status code to success and status enable
                        sms.setStatusCode(statusCode);
                        sms.setStatus(1);
                        jdbcSession.updateById(sms);

                    } else if (statusCode == -1) {
                        sms.setStatusCode(statusCode);
                        sms.setReviewReply(tempJson.getString("ReviewReply"));
                        updateOrSaveSmsTemplate(sms);
                    } else {
                        sms.setStatusCode(statusCode);
                        updateOrSaveSmsTemplate(sms);
                    }
                }
            }
        } catch (Exception e){
            return Result.error(0, "同步失败");
        }
        return Result.success(list);
    }

    public void init(String tagString, String title, String content,
        TemplateType templateType, MessageBusinessEnum businessEnum,
        int tencentTemplateId){
        MessageTemplateSms template = jdbcSession.findOne(MessageTemplateSms.class)
                                                   .eq("templateType", templateType)
                                                   .eq("status", 1)
                                                   .eq("deleted", false)
                                                   .exe();

        if (Objects.isNull(template)) {
            template = Pool.newInstance(MessageTemplateSms.class);
            template.setBusinessType(businessEnum);
            template.setTemplateType(templateType);
            template.setTagArray(tagString);
            template.setTitle(title);
            template.setContent(content);
            template.setTencentContent(TemplateReplaceUtil.replaceTencentSms(content));
            template.setTencentTemplateId(tencentTemplateId);
            template.setStatusCode(0);
            template.setInternational(1);
            template.setSmsType(0);
            template.setVariables(TemplateReplaceUtil.checkVariables(content));
            template.setStatus(1);
            jdbcSession.insert(template);
        } else {
            template.setBusinessType(businessEnum);
            template.setTemplateType(templateType);
            template.setTagArray(tagString);
            template.setTitle(title);
            template.setContent(content);
            template.setTencentContent(TemplateReplaceUtil.replaceTencentSms(content));
            template.setTencentTemplateId(tencentTemplateId);
            template.setStatusCode(0);
            template.setInternational(1);
            template.setSmsType(0);
            template.setVariables(TemplateReplaceUtil.checkVariables(content));
            template.setStatus(1);
            jdbcSession.updateById(template);
        }

        // sync global config
        resetGlobalConfig(template.getId());
        syncGlobalConfig(template.getBusinessType(), template.getTemplateType(), template.getId());
    }

    /**
     * 刷新短信模板，并重置消息提醒的模板引用
     */
    private Object refreshNewSmsTemplate(MessageTemplateSms sms) throws Exception {
        MessageTemplateSms temp = getSmsByInit(sms.getTemplateType().getId());
        if (Objects.nonNull(temp)) {
            if (temp.getTencentTemplateId() == 0) {
                setSms(temp);
                updateOrSaveSmsTemplate(temp);
                addTemplate(temp);
                return Result.success("已提交审核");
            }

            JSONObject queryJsonObject = tencentSmsService.queryTemplate(Arrays.asList(temp.getTencentTemplateId()));
            logger.info("查询模板{}返回：{}", sms.getId(), queryJsonObject.toJSONString());
            JSONArray queryResultArray = queryJsonObject.getJSONObject("Response").getJSONArray("DescribeTemplateStatusSet");
            if (Objects.isEmpty(queryResultArray)) {
                return Result.error(0,"不存在该模板");
            }

            JSONObject queryResultJson = queryResultArray.getJSONObject(0);
            Integer StatusCode = queryResultJson.getInteger("StatusCode");
            if (Objects.isNull(StatusCode)) {
                logger.error("queryTemplate查询异常：{}", queryJsonObject.toJSONString());
                return Result.error(0,"系统异常，请稍后重试");
            }

            // 刚申请的模板已审核通过啦~~~
            if (StatusCode == 0){// 0：表示审核通过。1：表示审核中。-1：表示审核未通过或审核失败
                // sync global config
                resetGlobalConfig(temp.getId());
                syncGlobalConfig(temp.getBusinessType(), temp.getTemplateType(), temp.getId());

                // reset status code to success and status enable
                temp.setStatusCode(StatusCode);
                temp.setStatus(1);
                jdbcSession.updateById(temp);

                if (!sms.getId().equals(temp.getId())) {
                    // reset status disabled
                    sms.setStatus(2);
                    updateOrSaveSmsTemplate(sms);
                }
                return Result.error(0, "系统存在刚审核通过的模板，如需再次更改，请稍后重试");
            } else if (StatusCode == -1) {
                sms.setStatusCode(StatusCode);
                sms.setReviewReply(queryResultJson.getString("ReviewReply"));
                updateOrSaveSmsTemplate(sms);
            } else {
                sms.setStatusCode(StatusCode);
                updateOrSaveSmsTemplate(sms);
            }
            setSms(temp);
            return Result.success();
        } else {
            if (sms.getTencentTemplateId() == 0) {
                setSms(sms);
                updateOrSaveSmsTemplate(sms);
                addTemplate(sms);
                return Result.success("已提交审核");
            }

            JSONObject queryJsonObject = tencentSmsService.queryTemplate(Arrays.asList(sms.getTencentTemplateId()));
            logger.info("查询模板{}返回：{}", sms.getId(), queryJsonObject.toJSONString());
            JSONArray queryResultArray = queryJsonObject.getJSONObject("Response").getJSONArray("DescribeTemplateStatusSet");
            if (Objects.isEmpty(queryResultArray)) {
                return Result.error(0,"不存在该模板");
            }

            JSONObject queryResultJson = queryResultArray.getJSONObject(0);
            Integer StatusCode = queryResultJson.getInteger("StatusCode");
            if (Objects.isNull(StatusCode)) {
                logger.error("queryTemplate查询异常：{}", queryJsonObject.toJSONString());
                return Result.error(0,"系统异常，请稍后重试");
            }

            // sync global config
            resetGlobalConfig(sms.getId());
            syncGlobalConfig(sms.getBusinessType(), sms.getTemplateType(), sms.getId());

            if (StatusCode == 0){// 0：表示审核通过。1：表示审核中。-1：表示审核未通过或审核失败
                // reset status enable
                // 0 init，1 enable，2 disabled
                sms.setStatus(1);
                sms.setStatusCode(StatusCode);
                updateOrSaveSmsTemplate(sms);
                return Result.error(0, "系统存在刚审核通过的模板，如需再次更改，请稍后重试");
            } else if (StatusCode == -1) {
                setSms(sms);
                sms.setReviewReply(queryResultJson.getString("ReviewReply"));
            } else {
                setSms(sms);
            }
            updateOrSaveSmsTemplate(sms);
            return Result.success();
        }
    }

    private void updateTemplate(MessageTemplateSms sms) throws Exception {
        JSONObject modifyJsonObject = tencentSmsService.updateTemplate(sms.getTitle(), sms.getTencentContent(), sms.getSmsType(), sms.getInternational(), sms.getRemark(), sms.getTencentTemplateId());
        logger.info("修改模板返回：{}", modifyJsonObject.toJSONString());
        JSONObject modifyResultJson = modifyJsonObject.getJSONObject("Response").getJSONObject("ModifyTemplateStatus");
        Integer templateId = modifyResultJson.getInteger("TemplateId");
        sms.setTencentTemplateId(templateId);
        jdbcSession.updateById(sms);
    }

    private void addTemplate(MessageTemplateSms temp) throws Exception {
        JSONObject addJsonObject = tencentSmsService.addTemplate(temp.getTitle(), temp.getTencentContent(), temp.getSmsType(), temp.getInternational(), temp.getRemark());
        logger.info("添加模板返回：{}", addJsonObject.toJSONString());
        JSONObject addResultJson = addJsonObject.getJSONObject("Response").getJSONObject("AddTemplateStatus");
        Integer templateId = addResultJson.getInteger("TemplateId");
        temp.setTencentTemplateId(templateId);
        jdbcSession.updateById(temp);
    }

    private void updateOrSaveSmsTemplate(MessageTemplateSms sms) {
        MessageTemplateSms templateSms = Pool.get(MessageTemplateSms.class, sms.getId());
        if (Objects.isNull(templateSms)) {
            jdbcSession.insert(sms);
        } else {
            jdbcSession.updateById(sms);
        }
    }

    private void resetGlobalConfig(String id){
        JSONObject json = new JSONObject();
        json.put("smsTemplate", id);
        globalConfigService.listGlobalConfig(json).forEach(e -> {
            e.setSmsTemplate(null);
            jdbcSession.updateById(e);
        });
    }
    private void syncGlobalConfig(MessageBusinessEnum businessState, TemplateType templateType, String id){
        MessageGlobalConfig globalConfig = globalConfigService.getGlobalConfig(templateType.getId());
        if (Objects.isNull(globalConfig)){
            globalConfig = Pool.newInstance(MessageGlobalConfig.class);
            globalConfig.setSmsTemplate(id);
            globalConfig.setBusinessEnum(businessState);
            globalConfig.setTemplateEnum(templateType);
            globalConfigService.save(globalConfig);
        } else {
            globalConfig.setSmsTemplate(id);
            globalConfig.setBusinessEnum(businessState);
            globalConfig.setTemplateEnum(templateType);
            globalConfigService.update(globalConfig);
        }
    }

    private void setSms(MessageTemplateSms sms){
        sms.setTencentContent(TemplateReplaceUtil.replaceTencentSms(sms.getContent()));
        sms.setStatusCode(1);// 模板状态:申请签名状态。其中：0：表示审核通过。1：表示审核中。-1：表示审核未通过或审核失败。
        sms.setInternational(0);// 是否国际/港澳台短信.0：表示国内短信,1：表示国际/港澳台短信
        sms.setSmsType(0);// 短信类型，0表示普通短信, 1表示营销短信
        sms.setVariables(TemplateReplaceUtil.checkVariables(sms.getContent()));
        sms.setStatus(0);
    }

    private boolean checkDuplicateByType(String id, TemplateType templateType){
        MessageTemplateSms template = jdbcSession.findOne(MessageTemplateSms.class)
                                                 .eq("templateType", templateType)
                                                 .eq("status", 0)
                                                 .eq("deleted", false)
                                                 .exe();
        return Objects.nonNull(template) && !id.equals(template.getId());
    }

    public MessageTemplateSms getSmsByInit(String templateType){
        return jdbcSession.findOne(MessageTemplateSms.class)
                          .eq("templateType", templateType)
                          .eq("status", 0)
                          .eq("deleted", false)
                          .exe();
    }

    public MessageTemplateSms getSmsByEnable(String templateType){
        return jdbcSession.findOne(MessageTemplateSms.class)
                          .eq("templateType", templateType)
                          .eq("status", 1)
                          .eq("deleted", false)
                          .exe();
    }

    @ReqMapping("/get")
    public Object get(String id){
        MessageTemplateSms sms = Pool.get(MessageTemplateSms.class, id);
        return Result.success(sms);
    }

}
